home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Add-On
/
Workbench Add-On - Volume 1.iso
/
BBS-Archive
/
Dev
/
gcc263-src.lha
/
gcc-2.6.3
/
config
/
clipper
/
clipper.md
< prev
next >
Wrap
Text File
|
1994-11-11
|
35KB
|
1,386 lines
;;- Machine description for GNU compiler, Clipper Version
;; Copyright (C) 1987, 1988, 1991, 1993, 1994 Free Software Foundation, Inc.
;; Contributed by Holger Teutsch (holger@hotbso.rhein-main.de)
;; This file is part of GNU CC.
;; GNU CC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; GNU CC is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU CC; see the file COPYING. If not, write to
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
;;- Instruction patterns. When multiple patterns apply,
;;- the first one in the file is chosen.
;;-
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
;;-
;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
;;- updates for most instructions.
;;
;; define attributes
;;
;; instruction type
;;
;; unknown is temporary in order to generate 'cc clobber' until attribute
;; assignment is consistent
;;
(define_attr "type" "load,store,arith,fp,branch,unknown"
(const_string "unknown"))
;; condition code setting
;;
;; clobber destroyed
;; unchanged
;; set1 set cc_status.value1, e.g. sub r0,r1
;; set2 set value1 and value2, e.g. mov r0,r1
;; change0 may be side effect, i.e. load mem,r0
;;
;; note: loadi and loadq are 'arith' instructions that set the condition codes
;; mul,div,mod do NOT set the condition codes
;;
(define_attr "cc" "clobber,unchanged,set1,set2,change0"
(cond [(eq_attr "type" "load") (const_string "change0")
(eq_attr "type" "store,branch") (const_string "unchanged")
(eq_attr "type" "arith") (if_then_else (match_operand:SI 0 "" "")
(const_string "set1")
(const_string "clobber"))
]
(const_string "clobber")))
;;
;; clipper seems to be a tradional risc processor
;; we define a functional unit 'memory'
;;
(define_function_unit "memory" 1 1 (eq_attr "type" "load") 4 0)
;; We don't want to allow a constant operand for test insns because
;; (set (cc0) (const_int foo)) has no mode information. Such insns will
;; be folded while optimizing anyway.
(define_insn "tstsi"
[(set (cc0)
(match_operand:SI 0 "int_reg_operand" "r"))]
""
"cmpq $0,%0")
(define_insn "cmpsi"
[(set (cc0)
(compare (match_operand:SI 0 "nonimmediate_operand" "r,r,n")
(match_operand:SI 1 "nonmemory_operand" "r,n,r")))]
""
"*
{
int val;
if (which_alternative == 0)
return \"cmpw %1,%0\";
if (which_alternative == 1)
{
val = INTVAL (operands[1]);
if (0 <= val && val < 16)
return \"cmpq %1,%0\";
return \"cmpi %1,%0\";
}
cc_status.flags |= CC_REVERSED; /* immediate must be first */
val = INTVAL (operands[0]);
if (0 <= val && val < 16)
return \"cmpq %0,%1\";
return \"cmpi %0,%1\";
}")
(define_insn "cmpdf"
[(set (cc0)
(compare (match_operand:DF 0 "fp_reg_operand" "f")
(match_operand:DF 1 "fp_reg_operand" "f")))]
""
"cmpd %1,%0")
(define_insn "cmpsf"
[(set (cc0)
(compare (match_operand:SF 0 "fp_reg_operand" "f")
(match_operand:SF 1 "fp_reg_operand" "f")))]
""
"cmps %1,%0")
;;
;; double and single float move
;;
(define_expand "movdf"
[(set (match_operand:DF 0 "general_operand" "")
(match_operand:DF 1 "general_operand" ""))]
""
"
{
if (GET_CODE (operands[0]) == MEM)
{
if (GET_CODE (operands[1]) == CONST_DOUBLE)
operands[1] = force_reg (DFmode,
force_const_mem (DFmode, operands[1]));
else if (GET_CODE (operands[1]) != REG)
operands[1] = force_reg (DFmode, operands[1]);
}
else if (GET_CODE (operands[1]) == CONST_DOUBLE)
operands[1] = force_const_mem (DFmode, operands[1]);
}")
;;
;; provide two patterns with different predicates as we don't want combine
;; to recombine a mem -> mem move
;;
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=*rf")
(match_operand:DF 1 "nonimmediate_operand" "*rfo"))]
""
"*
{
#define FP_REG_P(X) (GET_CODE (X) == REG && REGNO (X) >= 16)
if (FP_REG_P (operands[0]))
{
if (FP_REG_P (operands[1])) /* f -> f */
return \"movd %1,%0\";
if (GET_CODE (operands[1]) == REG) /* r -> f */
return \"movld %1,%0\";
return \"loadd %1,%0\"; /* m -> f */
}
if (FP_REG_P (operands[1]))
{
if (GET_CODE (operands[0]) == REG) /* f -> r */
return \"movdl %1,%0\";
abort ();
}
if (GET_CODE (operands[1]) == MEM) /* m -> r */
{
rtx xops[4];
xops[0] = operands[0];
xops[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
xops[2] = operands[1];
xops[3] = adj_offsettable_operand (operands[1], 4);
output_asm_insn (\"loadw %2,%0\;loadw %3,%1\", xops);
return \"\";
}
if (GET_CODE (operands[1]) == REG) /* r -> r */
{
rtx xops[4];
xops[0] = operands[0];
xops[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
xops[2] = operands[1];
xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
output_asm_insn (\"movw %2,%0\;movw %3,%1\", xops);
return \"\";
}
abort ();
#undef FP_REG_P
}")
(define_insn ""
[(set (match_operand:DF 0 "memory_operand" "=o,m")
(match_operand:DF 1 "register_operand" "*rf,f"))]
""
"*
{
rtx xops[4];
if (REGNO (operands[1]) >= 16) /* f -> m */
return \"stord %1,%0\";
xops[0] = operands[0]; /* r -> o */
xops[1] = adj_offsettable_operand (operands[0], 4);
xops[2] = operands[1];
xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
output_asm_insn (\"storw %2,%0\;storw %3,%1\", xops);
return \"\";
}"
[(set_attr "type" "store,store")
(set_attr "cc" "clobber,unchanged")])
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand" "")
(match_operand:SF 1 "general_operand" ""))]
""
"
{
if (GET_CODE (operands[0]) == MEM)
{
if (GET_CODE (operands[1]) == CONST_DOUBLE)
operands[1] = force_reg (SFmode,
force_const_mem (SFmode, operands[1]));
else if (GET_CODE (operands[1]) != REG)
operands[1] = force_reg (SFmode, operands[1]);
}
else if (GET_CODE (operands[1]) == CONST_DOUBLE)
operands[1] = force_const_mem (SFmode, operands[1]);
}")
;;
;; provide two patterns with different predicates as we don't want combine
;; to recombine a mem -> mem move
;;
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=*rf")
(match_operand:SF 1 "nonimmediate_operand" "*rfm"))]
""
"*
{
#define FP_REG_P(X) (GET_CODE (X) == REG && REGNO (X) >= 16)
if (FP_REG_P (operands[0]))
{
if (FP_REG_P (operands[1])) /* f -> f */
return \"movs %1,%0\";
if (GET_CODE (operands[1]) == REG) /* r -> f */
return
\"subq $8,sp\;storw %1,(sp)\;loads (sp),%0\;addq $8,sp\";
return \"loads %1,%0\"; /* m -> f */
}
if (FP_REG_P (operands[1]))
{
if (GET_CODE (operands[0]) == REG) /* f -> r */
return
\"subq $8,sp\;stors %1,(sp)\;loadw (sp),%0\;addq $8,sp\";
abort ();
}
if (GET_CODE (operands[1]) == MEM) /* m -> r */
return \"loadw %1,%0\";
if (GET_CODE (operands[1]) == REG) /* r -> r */
return \"movw %1,%0\";
abort ();
#undef FP_REG_P
}")
(define_insn ""
[(set (match_operand:SF 0 "memory_operand" "=m")
(match_operand:SF 1 "register_operand" "*rf"))]
""
"*
{
if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) >= 16)
return \"stors %1,%0\"; /* f-> m */
return \"storw %1,%0\"; /* r -> m */
}"
[(set_attr "type" "store")])
(define_expand "movdi"
[(set (match_operand:DI 0 "general_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
"
{
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) != REG)
operands[1] = force_reg (DImode, operands[1]);
}")
;; If an operand is a MEM but not offsetable, we can't load it into
;; a register, so we must force the third alternative to be the one
;; reloaded. Hence we show the first as more expensive.
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=?r,r,r")
(match_operand:DI 1 "general_operand" "r,n,o"))]
""
"*
{
rtx xoperands[2],yoperands[2];
xoperands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
if (which_alternative == 0) /* r -> r */
{
output_asm_insn (\"movw %1,%0\", operands);
xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
output_asm_insn (\"movw %1,%0\", xoperands);
return \"\";
}
if (which_alternative == 1) /* n -> r */
{
if (GET_CODE (operands[1]) == CONST_INT)
{
output_asm_insn (\"loadi %1,%0\", operands);
output_asm_insn (\"loadq $0,%0\", xoperands);
return \"\";
}
if (GET_CODE (operands[1]) != CONST_DOUBLE)
abort ();
yoperands[0] = operands[0];
yoperands[1] = gen_rtx (CONST_INT, VOIDmode,
CONST_DOUBLE_LOW (operands[1]));
output_asm_insn (\"loadi %1,%0\", yoperands);
xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
CONST_DOUBLE_HIGH (operands[1]));
output_asm_insn (\"loadi %1,%0\", xoperands);
return \"\";
}
/* m -> r */
output_asm_insn (\"loadw %1,%0\", operands);
xoperands[1] = adj_offsettable_operand (operands[1], 4);
output_asm_insn (\"loadw %1,%0\", xoperands);
return \"\";
}"
[(set_attr "type" "arith,arith,load")
(set_attr "cc" "clobber,clobber,clobber")])
(define_insn ""
[(set (match_operand:DI 0 "memory_operand" "=o")
(match_operand:DI 1 "register_operand" "r"))]
""
"*
{
rtx xops[4];
xops[0] = operands[0];
xops[1] = adj_offsettable_operand (operands[0], 4);
xops[2] = operands[1];
xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
output_asm_insn (\"storw %2,%0\;storw %3,%1\", xops);
return \"\";
}"
[(set_attr "type" "store")
(set_attr "cc" "clobber")])
(define_expand "movsi"
[(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
"
{
if (GET_CODE (operands[0]) == MEM &&
GET_CODE (operands[1]) != REG)
operands[1] = force_reg (SImode, operands[1]);
}")
;; Reject both args with `general_operand' if not reloading because a
;; mem -> mem move that was split by 'movsi' can be recombined to
;; mem -> mem by the combiner.
;;
;; As a pseudo register can end up in a stack slot during reloading we must
;; allow a r->m move for the next pattern.
;; The first predicate must be `general_operand' because a predicate must
;; be true for each constraint.
;;
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=r,r,r,r,m")
(match_operand:SI 1 "general_operand" "r,m,n,i,r"))]
"reload_in_progress || register_operand (operands[0], SImode)"
"*
{
int val;
if (which_alternative == 0)
return \"movw %1,%0\"; /* reg -> reg */
if (which_alternative == 1)
return \"loadw %1,%0\"; /* mem -> reg */
if (which_alternative == 2)
{
val = INTVAL (operands[1]); /* known const ->reg */
if (val == -1)
return \"notq $0,%0\";
if (val < 0 || val >= 16)
return \"loadi %1,%0\";
return \"loadq %1,%0\";
}
if (which_alternative == 3) /* unknown const */
return \"loada %a1,%0\";
return \"storw %1,%0\";
}"
[(set_attr "type" "arith,load,arith,load,store")
(set_attr "cc" "set2,change0,set1,change0,unchanged")])
(define_insn ""
[(set (match_operand:SI 0 "memory_operand" "=m")
(match_operand:SI 1 "int_reg_operand" "r"))]
""
"storw %1,%0"
[(set_attr "type" "store")])
;; movhi
;;
;; loadh mem to reg
;; storh reg to mem
;;
;;
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
"
{
if (GET_CODE (operands[0]) == MEM
&& ! register_operand (operands[1], HImode))
operands[1] = force_reg (HImode, operands[1]);
}")
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r,r")
(match_operand:HI 1 "general_operand" "r,m,n"))]
""
"@
movw %1,%0
loadh %1,%0
loadi %1,%0"
[(set_attr "type" "arith,load,arith")])
(define_insn ""
[(set (match_operand:HI 0 "memory_operand" "=m")
(match_operand:HI 1 "register_operand" "r"))]
""
"storh %1,%0"
[(set_attr "type" "store")])
;; movqi
;;
;; loadb mem to reg
;; storb reg to mem
;;
(define_expand "movqi"
[(set (match_operand:QI 0 "general_operand" "")
(match_operand:QI 1 "general_operand" ""))]
""
"
{
if (GET_CODE (operands[0]) == MEM &&
! register_operand (operands[1], QImode))
operands[1] = force_reg (QImode, operands[1]);
}")
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=r,r,r")
(match_operand:QI 1 "general_operand" "r,m,n"))]
""
"@
movw %1,%0
loadb %1,%0
loadi %1,%0"
[(set_attr "type" "arith,load,arith")])
(define_insn ""
[(set (match_operand:QI 0 "memory_operand" "=m")
(match_operand:QI 1 "register_operand" "r"))]
""
"storb %1,%0"
[(set_attr "type" "store")])
;;
;; block move
;;
(define_expand "movstrsi"
[(parallel
[(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:SI 2 "general_operand" ""))
(use (match_operand:SI 3 "const_int_operand" ""))
(clobber (match_scratch:SI 4 ""))
(clobber (match_scratch:SI 5 ""))
(clobber (match_dup 6))
(clobber (match_dup 7))])]
""
"
{
rtx addr0, addr1;
addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
operands[6] = addr0;
operands[7] = addr1;
operands[0] = gen_rtx (MEM, BLKmode, addr0);
operands[1] = gen_rtx (MEM, BLKmode, addr1);
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = force_reg (SImode, operands[2]);
}")
;;
;; there is a problem with this insn in gcc-2.2.3
;; (clobber (match_dup 2)) does not prevent use of this operand later
;; we always use a scratch register and leave operand 2 unchanged
;;
(define_insn ""
[(set (mem:BLK (match_operand:SI 0 "register_operand" "r"))
(mem:BLK (match_operand:SI 1 "register_operand" "r")))
(use (match_operand:SI 2 "nonmemory_operand" "rn"))
(use (match_operand:SI 3 "const_int_operand" "n"))
(clobber (match_scratch:SI 4 "=r"))
(clobber (match_scratch:SI 5 "=r"))
(clobber (match_dup 0))
(clobber (match_dup 1))]
""
"*
{
extern void clipper_movstr ();
clipper_movstr (operands);
return \"\";
}"
[(set_attr "cc" "clobber")])
;; Extension and truncation insns.
(define_insn "extendhisi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(sign_extend:SI (match_operand:HI 1 "general_operand" "0,m")))]
""
"@
andi $65535,%0\;xori $32768,%0\;subi $32768,%0
loadh %1,%0"
[(set_attr "type" "arith,load")])
(define_insn "extendqihi2"
[(set (match_operand:HI 0 "int_reg_operand" "=r,r")
(sign_extend:HI (match_operand:QI 1 "general_operand" "0,m")))]
""
"@
andi $255,%0\;xori $128,%0\;subi $128,%0
loadb %1,%0"
[(set_attr "type" "arith,load")
(set_attr "cc" "set1,change0")])
(define_insn "extendqisi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(sign_extend:SI (match_operand:QI 1 "general_operand" "0,m")))]
""
"@
andi $255,%0\;xori $128,%0\;subi $128,%0
loadb %1,%0"
[(set_attr "type" "arith,load")])
(define_insn "extendsfdf2"
[(set (match_operand:DF 0 "fp_reg_operand" "=f")
(float_extend:DF (match_operand:SF 1 "fp_reg_operand" "f")))]
""
"cnvsd %1,%0")
(define_insn "truncdfsf2"
[(set (match_operand:SF 0 "fp_reg_operand" "=f")
(float_truncate:SF (match_operand:DF 1 "fp_reg_operand" "f")))]
""
"cnvds %1,%0")
(define_insn "zero_extendhisi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(zero_extend:SI (match_operand:HI 1 "general_operand" "0,m")))]
""
"@
andi $65535,%0
loadhu %1,%0"
[(set_attr "type" "arith,load")])
(define_insn "zero_extendqihi2"
[(set (match_operand:HI 0 "int_reg_operand" "=r,r")
(zero_extend:HI (match_operand:QI 1 "general_operand" "0,m")))]
""
"@
andi $255,%0
loadbu %1,%0"
[(set_attr "type" "arith,load")
(set_attr "cc" "clobber,clobber")])
(define_insn "zero_extendqisi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(zero_extend:SI (match_operand:QI 1 "general_operand" "0,m")))]
""
"@
andi $255,%0
loadbu %1,%0"
[(set_attr "type" "arith,load")])
;; Fix-to-float conversion insns.
(define_insn "floatsisf2"
[(set (match_operand:SF 0 "fp_reg_operand" "=f")
(float:SF (match_operand:SI 1 "int_reg_operand" "r")))]
""
"cnvws %1,%0")
(define_insn "floatsidf2"
[(set (match_operand:DF 0 "fp_reg_operand" "=f")
(float:DF (match_operand:SI 1 "int_reg_operand" "r")))]
""
"cnvwd %1,%0")
;; Float-to-fix conversion insns.
(define_insn "fix_truncsfsi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(fix:SI (fix:SF (match_operand:SF 1 "fp_reg_operand" "f"))))]
""
"cnvtsw %1,%0")
(define_insn "fix_truncdfsi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(fix:SI (fix:DF (match_operand:DF 1 "fp_reg_operand" "f"))))]
""
"cnvtdw %1,%0")
;;- All kinds of add instructions.
(define_insn "adddf3"
[(set (match_operand:DF 0 "fp_reg_operand" "=f")
(plus:DF (match_operand:DF 1 "fp_reg_operand" "0")
(match_operand:DF 2 "fp_reg_operand" "f")))]
""
"addd %2,%0"
[(set_attr "type" "fp")])
(define_insn "addsf3"
[(set (match_operand:SF 0 "fp_reg_operand" "=f")
(plus:SF (match_operand:SF 1 "fp_reg_operand" "0")
(match_operand:SF 2 "fp_reg_operand" "f")))]
""
"adds %2,%0"
[(set_attr "type" "fp")])
(define_insn "adddi3"
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(plus:DI (match_operand:DI 1 "int_reg_operand" "%0")
(match_operand:DI 2 "int_reg_operand" "r")))]
""
"*
{
rtx xoperands[4];
xoperands[0] = operands[0];
xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
xoperands[2] = operands[2];
xoperands[3] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
output_asm_insn (\"addw %2,%0\;addwc %3,%1\", xoperands);
return \"\";
}"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
(define_insn "addsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r,r")
(plus:SI (match_operand:SI 1 "int_reg_operand" "%0,r,r")
(match_operand:SI 2 "nonmemory_operand" "rn,0,rn")))]
""
"*
{
if (which_alternative == 2) /* 3 address version */
{
if (GET_CODE (operands[2]) == CONST_INT)
return \"loada %a2(%1),%0\";
return \"loada [%2](%1),%0\";
}
/* 2 address version */
if (GET_CODE (operands[2]) == CONST_INT)
{
int val = INTVAL (operands[2]);
if (val >= 16 || val == 0x80000000)
return \"addi %2,%0\";
if (val < 0) /* change to sub */
{
rtx xops[2];
val = -val;
xops[0] = operands[0];
xops[1] = gen_rtx (CONST_INT, VOIDmode, val);
if (val >= 16)
output_asm_insn (\"subi %1,%0\", xops);
else
output_asm_insn (\"subq %1,%0\", xops);
return \"\";
}
return \"addq %2,%0\";
}
if (which_alternative == 0)
return \"addw %2,%0\";
return \"addw %1,%0\";
}"
[(set_attr "type" "arith,arith,arith")
(set_attr "cc" "set1,set1,change0")])
;;- All kinds of subtract instructions.
(define_insn "subdi3"
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(minus:DI (match_operand:DI 1 "int_reg_operand" "0")
(match_operand:DI 2 "int_reg_operand" "r")))]
""
"*
{
rtx xoperands[4];
xoperands[0] = operands[0];
xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
xoperands[2] = operands[2];
xoperands[3] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
output_asm_insn (\"subw %2,%0\;subwc %3,%1\", xoperands);
return \"\";
}"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
(define_insn "subsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(minus:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "rn")))]
""
"*
{
if (GET_CODE (operands[2]) == CONST_INT)
{
int val = INTVAL (operands[2]);
if (val < 0 || val >= 16)
return \"subi %2,%0\";
else
return \"subq %2,%0\";
}
return \"subw %2,%0\";
}"
[(set_attr "type" "arith")])
(define_insn "subdf3"
[(set (match_operand:DF 0 "fp_reg_operand" "=f")
(minus:DF (match_operand:DF 1 "fp_reg_operand" "0")
(match_operand:DF 2 "fp_reg_operand" "f")))]
""
"subd %2,%0"
[(set_attr "type" "fp")])
(define_insn "subsf3"
[(set (match_operand:SF 0 "fp_reg_operand" "=f")
(minus:SF (match_operand:SF 1 "fp_reg_operand" "0")
(match_operand:SF 2 "fp_reg_operand" "f")))]
""
"subs %2,%0"
[(set_attr "type" "fp")])
;;- Multiply instructions.
(define_insn "muldf3"
[(set (match_operand:DF 0 "fp_reg_operand" "=f")
(mult:DF (match_operand:DF 1 "fp_reg_operand" "0")
(match_operand:DF 2 "fp_reg_operand" "f")))]
""
"muld %2,%0"
[(set_attr "type" "fp")])
(define_insn "mulsf3"
[(set (match_operand:SF 0 "fp_reg_operand" "=f")
(mult:SF (match_operand:SF 1 "fp_reg_operand" "0")
(match_operand:SF 2 "fp_reg_operand" "f")))]
""
"muls %2,%0"
[(set_attr "type" "fp")])
(define_insn "mulsidi3"
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(mult:DI (sign_extend:DI (match_operand:SI 1 "int_reg_operand" "%0"))
(sign_extend:DI (match_operand:SI 2 "int_reg_operand" "r"))))]
""
"mulwx %2,%0"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
(define_insn "umulsidi3"
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(mult:DI (zero_extend:DI (match_operand:SI 1 "int_reg_operand" "%0"))
(zero_extend:DI (match_operand:SI 2 "int_reg_operand" "r"))))]
""
"mulwux %2,%0"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
(define_insn "mulsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(mult:SI (match_operand:SI 1 "int_reg_operand" "%0")
(match_operand:SI 2 "int_reg_operand" "r")))]
""
"mulw %2,%0"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
;;- Divide and mod instructions.
(define_insn "divdf3"
[(set (match_operand:DF 0 "fp_reg_operand" "=f")
(div:DF (match_operand:DF 1 "fp_reg_operand" "0")
(match_operand:DF 2 "fp_reg_operand" "f")))]
""
"divd %2,%0"
[(set_attr "type" "fp")])
(define_insn "divsf3"
[(set (match_operand:SF 0 "fp_reg_operand" "=f")
(div:SF (match_operand:SF 1 "fp_reg_operand" "0")
(match_operand:SF 2 "fp_reg_operand" "f")))]
""
"divs %2,%0"
[(set_attr "type" "fp")])
(define_insn "divsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(div:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "int_reg_operand" "r")))]
""
"divw %2,%0"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
(define_insn "udivsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(udiv:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "int_reg_operand" "r")))]
""
"divwu %2,%0"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
(define_insn "modsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(mod:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "int_reg_operand" "r")))]
""
"modw %2,%0"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
(define_insn "umodsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(umod:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "int_reg_operand" "r")))]
""
"modwu %2,%0"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
;;
;; bit and/or instructions
;;
(define_insn "andsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(and:SI (match_operand:SI 1 "int_reg_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "r,n")))]
""
"@
andw %2,%0
andi %2,%0"
[(set_attr "type" "arith")])
(define_insn "iorsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(ior:SI (match_operand:SI 1 "int_reg_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "r,n")))]
""
"@
orw %2,%0
ori %2,%0"
[(set_attr "type" "arith")])
(define_insn "xorsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(xor:SI (match_operand:SI 1 "int_reg_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "r,n")))]
""
"@
xorw %2,%0
xori %2,%0"
[(set_attr "type" "arith")])
(define_insn "negdf2"
[(set (match_operand:DF 0 "fp_reg_operand" "=f")
(neg:DF (match_operand:DF 1 "fp_reg_operand" "f")))]
""
"negd %1,%0"
[(set_attr "type" "fp")])
(define_insn "negsf2"
[(set (match_operand:SF 0 "fp_reg_operand" "=f")
(neg:SF (match_operand:SF 1 "fp_reg_operand" "f")))]
""
"negs %1,%0"
[(set_attr "type" "fp")])
(define_insn "negsi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(neg:SI (match_operand:SI 1 "int_reg_operand" "r")))]
""
"negw %1,%0"
[(set_attr "type" "arith")])
(define_insn "one_cmplsi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(not:SI (match_operand:SI 1 "int_reg_operand" "r")))]
""
"notw %1,%0"
[(set_attr "type" "arith")])
;; Right shift on the clipper works by negating the shift count,
;; then emitting a right shift with the shift count negated. This means
;; that all actual shift counts in the RTL will be positive.
(define_expand "ashrdi3"
[(set (match_operand:DI 0 "int_reg_operand" "")
(ashiftrt:DI (match_operand:DI 1 "int_reg_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(ashiftrt:DI (match_operand:DI 1 "int_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
""
"shali $%n2,%0"
[(set_attr "type" "arith")])
(define_insn ""
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(ashiftrt:DI (match_operand:DI 1 "int_reg_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))]
""
"shal %2,%0"
[(set_attr "type" "arith")])
(define_expand "ashrsi3"
[(set (match_operand:SI 0 "int_reg_operand" "")
(ashiftrt:SI (match_operand:SI 1 "int_reg_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(ashiftrt:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
""
"shai $%n2,%0"
[(set_attr "type" "arith")])
(define_insn ""
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(ashiftrt:SI (match_operand:SI 1 "int_reg_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))]
""
"shaw %2,%0"
[(set_attr "type" "arith")])
;;
;; left shift
;;
(define_insn "ashldi3"
[(set (match_operand:DI 0 "int_reg_operand" "=r,r")
(ashift:DI (match_operand:DI 1 "int_reg_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "r,n")))]
""
"@
shal %2,%0
shali %2,%0"
[(set_attr "type" "arith")])
(define_insn "ashlsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(ashift:SI (match_operand:SI 1 "int_reg_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "r,n")))]
""
"*
{
int val;
if (which_alternative == 0)
return \"shaw %2,%0\";
val = INTVAL (operands[2]);
if (val == 2)
return \"addw %0,%0\;addw %0,%0\";
if (val == 1)
return \"addw %0,%0\";
return \"shai %2,%0\";
}"
[(set_attr "type" "arith")])
;;
;; logical shift
;;
(define_expand "lshrdi3"
[(set (match_operand:DI 0 "int_reg_operand" "")
(lshiftrt:DI (match_operand:DI 1 "int_reg_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(lshiftrt:DI (match_operand:DI 1 "int_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
""
"shlli $%n2,%0"
[(set_attr "type" "arith")])
(define_insn ""
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(lshiftrt:DI (match_operand:DI 1 "int_reg_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))]
""
"shll %2,%0"
[(set_attr "type" "arith")])
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "int_reg_operand" "")
(lshiftrt:SI (match_operand:SI 1 "int_reg_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(lshiftrt:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
""
"shli $%n2,%0"
[(set_attr "type" "arith")])
(define_insn ""
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(lshiftrt:SI (match_operand:SI 1 "int_reg_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))]
""
"shlw %2,%0"
[(set_attr "type" "arith")])
;;
;; rotate insn
;;
(define_expand "rotrdi3"
[(set (match_operand:DI 0 "int_reg_operand" "")
(rotatert:DI (match_operand:DI 1 "int_reg_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(rotatert:DI (match_operand:DI 1 "int_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
""
"rotli $%n2,%0"
[(set_attr "type" "arith")])
(define_insn ""
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(rotatert:DI (match_operand:DI 1 "int_reg_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))]
""
"rotl %2,%0"
[(set_attr "type" "arith")])
(define_expand "rotrsi3"
[(set (match_operand:SI 0 "int_reg_operand" "")
(rotatert:SI (match_operand:SI 1 "int_reg_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(rotatert:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
""
"roti $%n2,%0"
[(set_attr "type" "arith")])
(define_insn ""
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(rotatert:SI (match_operand:SI 1 "int_reg_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))]
""
"rotw %2,%0"
[(set_attr "type" "arith")])
(define_insn "rotldi3"
[(set (match_operand:DI 0 "int_reg_operand" "=r,r")
(rotate:DI (match_operand:DI 1 "int_reg_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "r,n")))]
""
"@
rotl %2,%0
rotli %2,%0"
[(set_attr "type" "arith")])
(define_insn "rotlsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(rotate:SI (match_operand:SI 1 "int_reg_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "r,n")))]
""
"@
rotw %2,%0
roti %2,%0"
[(set_attr "type" "arith")])
;;
;; jump and branch insns
;;
(define_insn "jump"
[(set (pc)
(label_ref (match_operand 0 "" "")))]
""
"b %l0"
[(set_attr "type" "branch")])
(define_insn "tablejump"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))
(use (label_ref (match_operand 1 "" "")))]
""
"b (%0)"
[(set_attr "type" "branch")])
(define_insn "beq"
[(set (pc)
(if_then_else (eq (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"breq %l0"
[(set_attr "type" "branch")])
(define_insn "bne"
[(set (pc)
(if_then_else (ne (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brne %l0"
[(set_attr "type" "branch")])
(define_insn "bgt"
[(set (pc)
(if_then_else (gt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brgt %l0"
[(set_attr "type" "branch")])
(define_insn "bgtu"
[(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brgtu %l0"
[(set_attr "type" "branch")])
(define_insn "blt"
[(set (pc)
(if_then_else (lt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brlt %l0"
[(set_attr "type" "branch")])
(define_insn "bltu"
[(set (pc)
(if_then_else (ltu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brltu %l0"
[(set_attr "type" "branch")])
(define_insn "bge"
[(set (pc)
(if_then_else (ge (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brge %l0"
[(set_attr "type" "branch")])
(define_insn "bgeu"
[(set (pc)
(if_then_else (geu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brgeu %l0"
[(set_attr "type" "branch")])
(define_insn "ble"
[(set (pc)
(if_then_else (le (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brle %l0"
[(set_attr "type" "branch")])
(define_insn "bleu"
[(set (pc)
(if_then_else (leu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brleu %l0"
[(set_attr "type" "branch")])
;; Recognize reversed jumps.
(define_insn ""
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(cc0)
(const_int 0)])
(pc)
(label_ref (match_operand 1 "" ""))))]
""
"br%C0 %l1" ; %C0 negates condition
[(set_attr "type" "branch")])
;;
;; call instructions
;;
(define_insn "call"
[(call (match_operand:QI 0 "general_operand" "m")
(match_operand:SI 1 "general_operand" ""))]
;; Operand 1 not used on the clipper.
""
"call sp,%0")
(define_insn "call_value"
[(set (match_operand 0 "" "=rf")
(call (match_operand:QI 1 "general_operand" "m")
(match_operand:SI 2 "general_operand" "g")))]
;; Operand 2 not used on the clipper
""
"call sp,%1")
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))]
""
"b (%0)"
[(set_attr "type" "branch")])
(define_insn "nop"
[(const_int 0)]
""
"noop"
[(set_attr "type" "arith")
(set_attr "cc" "unchanged")])
;; while (--foo >= 0)
;;
;; Combiners for 'decrement test and branch' do not work for clipper.
;; These patters are jump_insns that do not allow output reloads and clipper
;; can only decrement and test registers.
;;